package org.zhuzx.util.storage;

import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

public enum DataContainer {
	SingleValue(0) {
		public <E> SingleValueCollection<E> getFilledContainer(E[] data) {
			SingleValueCollection<E> container = new SingleValueCollection<>();
			if (data.length > 0) {
				container.setElement(data[0]);
			}
			return container;
		}
		public <E> SingleValueCollection<E> getEmptyContainer() {
			return new SingleValueCollection<>();
		}
	},
	HashSet(1) {
		public <E> HashSet<E> getFilledContainer(E[] data) {
			HashSet<E> container = new HashSet<E>(data.length);
			for (E e : data) {
				container.add(e);
			}
			return container;
		}
		public <E> HashSet<E> getEmptyContainer() {
			return new HashSet<E>();
		}
	},
	ArrayList(2) {
		public <E> ArrayList<E> getFilledContainer(E[] data) {
			ArrayList<E> container = new ArrayList<E>(data.length);
			for (E e : data) {
				container.add(e);
			}
			return null;
		}
		public <E> ArrayList<E> getEmptyContainer() {
			return new ArrayList<E>();
		}
	};
	
	private int containerCode;
	private DataContainer(int containerCode) {
		this.containerCode = containerCode;
	}
	public int getContainerCode() {
		return this.containerCode;
	}
	
	public abstract <E> Collection<E> getEmptyContainer();
	public abstract <E> Collection<E> getFilledContainer(E[] data);
	
	private static final DataContainer[] types = getTypes();
	private static DataContainer[] getTypes() {
		DataContainer[] values = values();
		int maxCode = 0;
		for (DataContainer dataContainer : values) {
			maxCode = Math.max(dataContainer.getContainerCode(), maxCode);
		}
		DataContainer[] array = new DataContainer[maxCode+1];
		for (DataContainer dataContainer : values) {
			if (array[dataContainer.getContainerCode()] != null) return null;
			array[dataContainer.getContainerCode()] = dataContainer;
		}
		return array;
	}
	
	public static DataContainer getDataContainer(int containerCode) {
		return types[containerCode];
	}
	
	public static class SingleValueCollection<E> extends AbstractCollection<E> {
		private E element;
		public SingleValueCollection() {
			super();
		}
		@Override
		public Iterator<E> iterator() {
			return null;
		}
		@Override
		public int size() {
			return 1;
		}
		public E getElement() {
			return element;
		}
		public void setElement(E element) {
			this.element = element;
		}
	};
}